﻿using System;
using System.Windows.Input;
using System.Windows.Threading;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.ObjectModel;

namespace mal.WP7.StopwatchTimer.ViewModels
{
    public class StopwatchViewModel : ViewModelBase
    {
        #region Fields
        private TimeSpan totalTime = TimeSpan.FromSeconds(-1);
        private string totalTimeString;
        private string totalMillisconds;

        private TimeSpan lapTime = TimeSpan.FromSeconds(-1);
        private string lapMillisconds;
        private string lapTimeString;


        private RelayCommand playPauseCommand;
        private RelayCommand lapCommand;
        private RelayCommand resetCommand;
        
			
        private ObservableCollection<Lap> laps;




        private DispatcherTimer timer;

        private DateTime startDate;
        private DateTime lapStartDate;
        #endregion

        #region Construction / Destruction
        public StopwatchViewModel()
        {
            timer = new DispatcherTimer();
            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = TimeSpan.FromMilliseconds(5);
            Initialize();
        }

        

        #endregion

        #region enum, struct, class
        public class Lap
        {
            public Lap(int number, TimeSpan time)
            {
                Number = number;
                Time = time;
                TimeString = string.Format("{0:00}:{1:00}:{2:00},{3:00}"
                            , (int)Time.TotalHours, Time.Minutes, Time.Seconds, Time.Milliseconds/10);
            }

            public int Number { get; private set; }
            public TimeSpan Time { get; private set; }
            public string TimeString { get; private set; }
        }
        #endregion

        #region Properties
        public string LapMillisconds
        {
            get { return lapMillisconds; }
            set
            {
                if (lapMillisconds != value)
                {
                    lapMillisconds = value;
                    RaisePropertyChanged("LapMillisconds");
                }
            }
        }

        public TimeSpan LapTime
        {
            get { return lapTime; }
            set
            {
                if (lapTime != value)
                {
                    lapTime = value;
                    RaisePropertyChanged("LapTime");

                    this.LapMillisconds = string.Format("{0:00}", lapTime.Milliseconds/10);
                    this.LapTimeString = string.Format("{0:00}:{1:00}:{2:00}"
                            , (int)LapTime.TotalHours, LapTime.Minutes, LapTime.Seconds);
                }
            }
        }

        public string LapTimeString
        {
            get { return lapTimeString; }
            set
            {
                if (lapTimeString != value)
                {
                    lapTimeString = value;
                    RaisePropertyChanged("LapTimeString");
                }
            }
        }

        public string TotalMillisconds
        {
            get { return totalMillisconds; }
            set
            {
                if (totalMillisconds != value)
                {
                    totalMillisconds = value;
                    RaisePropertyChanged("TotalMillisconds");

                }
            }
        }

        public TimeSpan TotalTime
        {
            get { return totalTime; }
            set
            {
                if (totalTime != value)
                {
                    totalTime = value;
                    RaisePropertyChanged("TotalTime");
                    this.TotalMillisconds = string.Format("{0:00}", totalTime.Milliseconds/10);
                    this.TotalTimeString = string.Format("{0:00}:{1:00}:{2:00}"
                            , (int)TotalTime.TotalHours, TotalTime.Minutes, TotalTime.Seconds);
                }
            }
        }

        public string TotalTimeString
        {
            get { return totalTimeString; }
            set
            {
                if (totalTimeString != value)
                {
                    totalTimeString = value;
                    RaisePropertyChanged("TotalTimeString");
                }
            }
        }

        public ObservableCollection<Lap> Laps
        {
            get { return laps; }
            set
            {
                if (laps != value)
                {
                    laps = value;
                    RaisePropertyChanged("Laps");
                }
            }
        }

        public ICommand PlayPauseCommand
        {
            get
            {
                if (this.playPauseCommand == null)
                {
                    this.playPauseCommand = new RelayCommand(OnPlayPauseCommand);
                }
                return this.playPauseCommand;
            }
        }

        public ICommand LapCommand
        {
            get
            {
                if (this.lapCommand == null)
                {
                    this.lapCommand = new RelayCommand(OnLap);
                }
                return this.lapCommand;
            }
        }

        public ICommand ResetCommand
        {
            get
            {
                if (this.resetCommand == null)
                {
                    this.resetCommand = new RelayCommand(OnReset);
                }
                return this.resetCommand;
            }
        }        
        #endregion

        #region Methods
        private void Initialize()
        {
            this.TotalTime = TimeSpan.FromSeconds(0);
            this.LapTime = TimeSpan.FromSeconds(0);

            Laps = new ObservableCollection<Lap>();
        }

        #endregion

        #region Events
        void timer_Tick(object sender, EventArgs e)
        {
            DateTime now = DateTime.Now;
            this.TotalTime = now.Subtract(startDate);
            this.LapTime = now.Subtract(lapStartDate);
        }

        protected void OnPlayPauseCommand()
        {
            if (this.timer.IsEnabled)
            {
                this.timer.Stop();
            }
            else
            {
                DateTime now = DateTime.Now;
                startDate = now.Subtract(this.TotalTime);
                lapStartDate = now.Subtract(this.LapTime);

                this.timer.Start();
            }
        }

        protected void OnReset()
        {
            if (this.timer.IsEnabled)
            {
                this.timer.Stop();
            }

            Initialize();
        }

        protected void OnLap()
        {
            TimeSpan lap = this.LapTime;
            lapStartDate = DateTime.Now;
            Laps.Add(new Lap(Laps.Count + 1, lap));
        }
        #endregion


    }
}
